<?php
declare (strict_types = 1);

namespace ui;

use exception\FriendlyException;

/**
 * 
 */
class Form {

    private $fieldLines = [];
    private $buttons = [];

    // 表单模式
    public const MODE_NORMAL = '';
    public const MODE_DIALOG = 'DIALOG';
    private $mode = self::MODE_NORMAL;

    // 表单提交地址
    private $url = '';

    // 表单标题
    private $title = '';

    // 是否显示遮罩
    private $mask = true;
    // 是否允许点击遮罩层关闭
    private $maskClosable = false;
    // 是否可以拖拽移动
    private $draggable = false;
    // 宽度
    private $width = 520;
    private $top = '10vh';
    private $maxHeight = '50vh';

    private $inFieldLine = false;
    private $fieldLineSpans = [];

    public static function create() {
        $builder = new Form();
        return $builder;
    }

    public static function createDialogBuilder($title, $options = []) {
        $builder = new Form();
        $builder->setTitle($title);
        $builder->setDialogMode();
        $builder->maskClosable = isset($options['mask_closable']) ? $options['mask_closable'] : false;
        isset($options['width']) ? $builder->width = $options['width'] : '';
        isset($options['top']) ? $builder->top = $options['top'] : '';
        isset($options['maxHeight']) ? $builder->maxHeight = $options['maxHeight'] : '';
        return $builder;
    }

    public function addField(FormField $field) {
        if($this->inFieldLine) {
            $len = count($this->fieldLines[count($this->fieldLines) - 1]);
            if(isset($this->fieldLineSpans[$len])) {
                $field->setSpan($this->fieldLineSpans[$len]);
            }
            $this->fieldLines[count($this->fieldLines) - 1][] = $field;
        } else {
            $this->fieldLines[] = [$field];
        }
        return $this;
    }

    public function beginLine($fieldLineSpans = []) {
        if($this->inFieldLine) {
            $this->endLine();
        }
        $this->inFieldLine = true;
        $this->fieldLineSpans = $this->toSpan($fieldLineSpans);
        $this->fieldLines[] = [];
        return $this;
    }

    private function toSpan($fieldLineSpans) {
        $sum = 0;
        foreach ($fieldLineSpans as $s) {
            $sum += $s;
        }
        if($sum == 0) return [];
        if($sum == 24) return $fieldLineSpans;
        if(24 % $sum !== 0) throw new FriendlyException("行比例必须为24倍数");
        $pow = 24 / $sum;
        $result = [];
        foreach ($fieldLineSpans as $s) {
            $result[] = $s * $pow;
        }
        return $result;
    }
    
    public function endLine() {
        $this->inFieldLine = false;
        $this->fieldLineSpans = [];
        foreach ($this->fieldLines[count($this->fieldLines) - 1] as &$field) {
            if(empty($field->getSpan())) {
                $field->setSpan(intval(24 / count($this->fieldLines[count($this->fieldLines) - 1])));
            }
        }
        return $this;
    }

    public function addButton(Button $button) {
        $this->buttons[] = $button->build();
        return $this;
    }

    public function addConfirmButton($url) {
        $this->addButton(Button::create('submit', $url)->setLabel('确认'));
        return $this;
    }

    public function addCancleButton() {
        $this->addButton(Button::createText('cancle', Event::create('cancle'))->setLabel('取消'));
        return $this;
    }

    public function setTitle($title) {
        $this->title = $title;
        return $this;
    }

    public function setDialogMode() {
        $this->mode = self::MODE_DIALOG;
        return $this;
    }

    public function build() {
        $lines = [];
        foreach ($this->fieldLines as $line) {
            $newLine = [];
            foreach ($line as $field) {
                $newLine[] = $field->build();
            }
            $lines[] = $newLine;
        }
        return [
            'mode' => $this->mode,
            'title' => $this->title,
            'mask' => $this->mask,
            'maskClosable' => $this->maskClosable,
            'draggable' => $this->draggable,
            'width' => $this->width,
            'top' => $this->top,
            'maxHeight' => $this->maxHeight,
            'buttons' => $this->buttons,
            'lines' => $lines,
            'url' => $this->url,
            'query' => $_GET,
        ];
    }

    public function buildJson() {
        return json_encode($this->build());
    }
}
